home *** CD-ROM | disk | FTP | other *** search
/ Amiga CD-ROM Collection / Amiga CD-ROM Collection - Auge 4000 and Cactus and Demo Util.iso / auge4000 / 15 / wblander / source / rocket.c < prev    next >
C/C++ Source or Header  |  1987-12-02  |  21KB  |  1,035 lines

  1. #include <exec/types.h>
  2. #include <exec/devices.h>
  3. #include <exec/memory.h>
  4. #include <graphics/gfx.h>
  5. #include <devices/gameport.h>
  6. #include <devices/inputevent.h>
  7. #include <intuition/intuition.h>
  8. #include <graphics/sprite.h>
  9. #include <devices/timer.h>
  10. #include <hardware/custom.h>
  11. #include <stdio.h> 
  12. #include <ctype.h> 
  13. #include "flame.h"
  14. #include "sample.h"
  15. #include "sounds.h"
  16.  
  17. #define INTUITION_REV 1 
  18. #define GRAPHICS_REV  1 
  19. #define LAYERS_REV  1
  20.  
  21. #define SAUCERSPEED 200
  22. #define SAUCERDELAY 370
  23. #define ROCKETHEIGHT 16
  24. #define SPRWIDTH 32
  25. #define PIXRATIO 2
  26. #define SCALEFACTOR 100
  27. #define XMAX (640*SCALEFACTOR)
  28. #define YMAX (200*SCALEFACTOR)
  29. #define XMIN (-(SPRWIDTH/PIXRATIO)*SCALEFACTOR)
  30. #define YMIN (-ROCKETHEIGHT*SCALEFACTOR)
  31.  
  32. #define OK 0
  33. #define LANDED 1
  34. #define CRASHEDGOOD 2
  35. #define CRASHEDBAD 3
  36. #define CRASHEDSAUCER 4
  37.  
  38. #define MAINFLAME 4
  39. #define LEFTFLAME 1
  40. #define RIGHTFLAME 2
  41.  
  42. #define ALLFLAMES (MAINFLAME|LEFTFLAME|RIGHTFLAME)
  43.  
  44. USHORT rocket_image[ROCKETHEIGHT*2] = {
  45.     0x0000, 0x0000,
  46.     0x0000, 0x0000,
  47.     0x0100, 0x0100,
  48.     0x0100, 0x0100,
  49.     0x0380, 0x0380,
  50.     0x0380, 0x0380,
  51.     0x07c0, 0x07c0,
  52.     0x07c0, 0x07c0,
  53.     0x0fe0, 0x0fe0,
  54.     0x0fe0, 0x0fe0,
  55.     0x0820, 0x0820,
  56.     0x0820, 0x0820,
  57.     0x0820, 0x0820,
  58.     0x0000, 0x0000,
  59.     0x0000, 0x0000,
  60.     0x0000, 0x0000,
  61. };
  62. USHORT flame[3][ROCKETHEIGHT*2] = {
  63. {
  64.     0x0000, 0x0000,
  65.     0x0000, 0x0000,
  66.     0x0100, 0x0100,
  67.     0x0100, 0x0100,
  68.     0x0380, 0x0380,
  69.     0x0380, 0x0380,
  70.     0x07c0, 0x07c0,
  71.     0x0fc0, 0x37c0,
  72.     0x0fe0, 0x0fe0,
  73.     0x0fe0, 0x0fe0,
  74.     0x0820, 0x0820,
  75.     0x0820, 0x0820,
  76.     0x0820, 0x0820,
  77.     0x0000, 0x0000,
  78.     0x0000, 0x0000,
  79.     0x0000, 0x0000,
  80. },
  81. {
  82.     0x0000, 0x0000,
  83.     0x0000, 0x0000,
  84.     0x0100, 0x0100,
  85.     0x0100, 0x0100,
  86.     0x0380, 0x0380,
  87.     0x0380, 0x0380,
  88.     0x07c0, 0x07c0,
  89.     0x07e0, 0x07d8,
  90.     0x0fe0, 0x0fe0,
  91.     0x0fe0, 0x0fe0,
  92.     0x0820, 0x0820,
  93.     0x0820, 0x0820,
  94.     0x0820, 0x0820,
  95.     0x0000, 0x0000,
  96.     0x0000, 0x0000,
  97.     0x0000, 0x0000,
  98. },
  99. {
  100.     0x0000, 0x0000,
  101.     0x0000, 0x0000,
  102.     0x0100, 0x0100,
  103.     0x0100, 0x0100,
  104.     0x0380, 0x0380,
  105.     0x0380, 0x0380,
  106.     0x07c0, 0x07c0,
  107.     0x07c0, 0x07c0,
  108.     0x0fe0, 0x0fe0,
  109.     0x0fe0, 0x0fe0,
  110.     0x0ba0, 0x0c60,
  111.     0x0920, 0x0ee0,
  112.     0x0920, 0x0aa0,
  113.     0x0000, 0x0380,
  114.     0x0000, 0x0100,
  115.     0x0000, 0x0100,
  116. }
  117. };
  118. USHORT sprite_colors[3] = { 0x059f, 0x044d, 0x0bc0 };
  119. #define SAUCERHEIGHT 5
  120. USHORT saucer_image[3][SAUCERHEIGHT*2] = {
  121. {
  122.     0x0ff0, 0x0ff0,
  123.     0xffff, 0xffff,
  124.     0xb6db, 0x6db6,
  125.     0xffff, 0xffff,
  126.     0x0ff0, 0x0ff0
  127. },
  128. {
  129.     0x0ff0, 0x0ff0,
  130.     0xffff, 0xffff,
  131.     0x6db6, 0xdb6d,
  132.     0xffff, 0xffff,
  133.     0x0ff0, 0x0ff0
  134. },
  135. {
  136.     0x0ff0, 0x0ff0,
  137.     0xffff, 0xffff,
  138.     0xdb6d, 0xb6db,
  139.     0xffff, 0xffff,
  140.     0x0ff0, 0x0ff0
  141. }
  142. };
  143.  
  144. UWORD *rbuf, *sbuf;
  145. struct SimpleSprite rocket, saucer;
  146. int rocket_sprite, saucer_sprite;
  147. struct Window *window, *badwindow;
  148. struct ViewPort *viewport;
  149. struct Remember *Memory;
  150.  
  151. /*   Intuition always wants to see these declarations */
  152. struct IntuitionBase *IntuitionBase;
  153. struct GfxBase *GfxBase;
  154. struct Library *LayersBase;
  155.  
  156. /* my window structure */
  157. struct NewWindow NewWindow = {
  158.     200,  140, 
  159.     300,  10, 
  160.     0,    1, 
  161.     CLOSEWINDOW | RAWKEY,
  162.     ACTIVATE | WINDOWCLOSE | SMART_REFRESH | WINDOWDRAG | WINDOWDEPTH,
  163.     NULL, 
  164.     NULL, 
  165.     "Workbench Lander", 
  166.     NULL, 
  167.     NULL, 
  168.     0, 0, 
  169.     0, 0, 
  170.     WBENCHSCREEN, 
  171. };
  172.  
  173. struct NewWindow BadWindow = {
  174.     200, 101,
  175.     300, 10,
  176.     0, 1,
  177.     CLOSEWINDOW,
  178.     WINDOWCLOSE | SMART_REFRESH | WINDOWDRAG | WINDOWDEPTH,
  179.     NULL,
  180.     NULL,
  181.     "Don't land here...",
  182.     NULL,
  183.     NULL,
  184.     0, 0,
  185.     0, 0,
  186.     WBENCHSCREEN,
  187. };
  188. struct IntuiMessage *NewMessage;
  189.  
  190. struct IOAudio *DoneMessage;
  191. extern Sound eagle1sound, eagle2sound;
  192.  
  193. struct InputEvent gameEvent;
  194. struct MsgPort *gameMsgPort;
  195. struct IOStdReq *gameIOMsg;
  196. int ControllerType;
  197. int GameportOpen;
  198. int gameIOPending;
  199.  
  200. struct timerequest *tr;
  201.  
  202. /******************************************************/
  203. /*                   Main Program                     */
  204. /*                                                    */
  205. /*      This is the main body of the program.         */
  206. /******************************************************/
  207.  
  208. int x, y, vx, vy, ax, ay;
  209. int buttons = 0;
  210.  
  211. char *cycle[] = {
  212.     "Workbench Lander",
  213.     "Use joystick to",
  214.     "Land on this window",
  215.     "Workbench Lander",
  216.     "Don't hit too hard",
  217.     "Don't fall over",
  218.     "Don't get caught",
  219.     "Workbench Lander",
  220.     "Space is big",
  221.     "Space is dark",
  222.     "It's hard to find",
  223.     "A place to park",
  224.     "BURMA SHAVE",
  225.     "Workbench Lander",
  226.     "Another fine hack",
  227.     "by Peter da Silva",
  228.     "with audio by ",
  229.     "Karl Lehenbauer",
  230.     "Workbench Lander",
  231.     "Pass it around",
  232.     "Call our board",
  233.     "Wintermute",
  234.     "(713) 933-2440",
  235.     "Or on usenet...",
  236.     "...!hoptoad!academ...",
  237.     "...!uhnix1!sugar...",
  238.     "...!{karl,peter}",
  239.     0
  240. };
  241. int cycle_position, cycle_timeout;
  242.  
  243. char *title[] = {
  244.     "Workbench Lander 2.1 \251 1987 Sugarland Software",
  245.     "Usenet: ...!hoptoad!academ!uhnix1!sugar!{karl,peter}"
  246. };
  247. int titmode;
  248.  
  249. display_cycle()
  250. {
  251.     int newmode;
  252.     char *msg;
  253.  
  254.     if(cycle[cycle_position][0]=='O' ||
  255.        cycle[cycle_position][0]=='(' ||
  256.        cycle[cycle_position][0]=='.')
  257.         newmode = 1;
  258.     else
  259.         newmode = 0;
  260.     if(newmode == titmode)
  261.         msg = -1;
  262.     else {
  263.         msg = title[newmode];
  264.         titmode = newmode;
  265.     }
  266.  
  267.     SetWindowTitles(window, cycle[cycle_position], msg);
  268. }
  269.  
  270. addflame(n)
  271. int n;
  272. {
  273.     if (!(buttons&n)) ThrustAudio(n);
  274.     buttons |= n;
  275.     recalc_rocket();
  276. }
  277.  
  278. delflame(n)
  279. int n;
  280. {
  281.     if (buttons&n) ThrustQuiet(n);
  282.     buttons &= ~n;
  283.     recalc_rocket();
  284. }
  285.  
  286. JoyMove(x, y)
  287. int x, y;
  288. {
  289.     static int lastx = 0, lasty = 0;
  290.  
  291.     if(x<-1) x = -1;
  292.     if(x>1) x = 1;
  293.     if(y<-1) y = -1;
  294.     if(y>1) y = 1;
  295.     if(x!=lastx)
  296.         switch(x) {
  297.             case -1:
  298.                 addflame(RIGHTFLAME);
  299.                 ax = -10;
  300.                 break;
  301.             case 0:
  302.                 delflame(LEFTFLAME|RIGHTFLAME);
  303.                 ax = 0;
  304.                 break;
  305.             case 1:
  306.                 addflame(LEFTFLAME);
  307.                 ax = 10;
  308.                 break;
  309.         }
  310.     if(y!=lasty)
  311.         if(y==-1) {
  312.             addflame(MAINFLAME);
  313.             ay = -20;
  314.         }  else {
  315.             delflame(MAINFLAME);
  316.             ay = 10;
  317.         }
  318.     lastx = x;
  319.     lasty = y;
  320. }
  321.  
  322. recalc_rocket()
  323. {
  324.     int b, i;
  325.     rbuf[0] = rbuf[1] = 0;
  326.     for(i = 0; i < 2*ROCKETHEIGHT; i++)
  327.         rbuf[i+2] = rocket_image[i];
  328.     rbuf[2*ROCKETHEIGHT+2] = 0;
  329.     rbuf[2*ROCKETHEIGHT+3] = 0;
  330.  
  331.     for(b = 0; b < 3; b++)
  332.         if(buttons & (1<<b))
  333.             for(i = 0; i < 2*ROCKETHEIGHT; i++)
  334.                 rbuf[i+2] |= flame[b][i];
  335.  
  336.     ChangeSprite(viewport, &rocket, rbuf);
  337. }
  338.  
  339. set_saucer(n)
  340. int n;
  341. {
  342.     int i;
  343.  
  344.     sbuf[0] = sbuf[1] = 0;
  345.     for(i = 0; i < 2*SAUCERHEIGHT; i++)
  346.         sbuf[i+2] = saucer_image[n][i];
  347.     sbuf[2*SAUCERHEIGHT+2] = 0;
  348.     sbuf[2*SAUCERHEIGHT+3] = 0;
  349.  
  350.     ChangeSprite(viewport, &saucer, sbuf);
  351. }
  352.  
  353. #define BEGIN_EXPLOSION 0
  354. #define IN_EXPLOSION 1
  355. #define END_EXPLOSION 2
  356. int exploding;
  357. int coloregs;
  358. int counter;
  359.  
  360. int KeepGoing;
  361. int timeout;
  362. int saucer_timeout, saucer_x, saucer_y, saucer_cycle, saucer_up;
  363. int autoflag;
  364. int automode;
  365.         /* 'F' -- fall.
  366.          * 'G' -- go there.
  367.          * 'H' -- hover
  368.          * 'L' -- land it
  369.          * 'P' -- pause
  370.          */
  371.  
  372. explode()
  373. {
  374.     int i;
  375.  
  376.     if(!exploding) {
  377.         SaucerQuiet();
  378.         CrashAudio();
  379.         counter = 21;
  380.         exploding = 1;
  381.     }
  382.     if(counter-- < 0) {
  383.         reinit();
  384.         for(i = 0; i < 3; i++)
  385.             SetRGB4(viewport, coloregs+1+i,
  386.                 sprite_colors[i]&0x000F,
  387.                 (sprite_colors[i]&0x00F0)>>4,
  388.                 (sprite_colors[i]&0x0F00)>>8);
  389.         CrashQuiet();
  390.     } else {
  391.         for(i = 0; i < 3; i++)
  392.             SetRGB4(viewport, coloregs+1+i,
  393.                 RangeRand(16),
  394.                 RangeRand(16),
  395.                 RangeRand(16));
  396.     }
  397. }
  398.  
  399. reinit()
  400. {
  401.     exploding = 0;
  402.     x = y = 200;
  403.     vx = 100;
  404.     vy = 0;
  405.     ax = 0;
  406.     ay = 10;
  407.     automode = 'F';
  408.     delflame(ALLFLAMES);
  409.     saucer_timeout = SAUCERDELAY;
  410.     timeout = 10;
  411. }
  412.  
  413. int debug = 0;
  414.  
  415. main_cleanup()
  416. {
  417.     if(saucer_sprite > 0)
  418.         FreeSprite(saucer_sprite);
  419.     if(rocket_sprite > 0)
  420.         FreeSprite(rocket_sprite);
  421.     FreeRemember(&Memory, TRUE);
  422.     if(badwindow)
  423.         CloseWindow(badwindow);
  424.     if(window)
  425.         CloseWindow(window);
  426.     if(GfxBase)
  427.         CloseLibrary(GfxBase);
  428.     if(LayersBase)
  429.         CloseLibrary(LayersBase);
  430.     if(IntuitionBase)
  431.         CloseLibrary(IntuitionBase);
  432. }
  433.  
  434. main()
  435. {
  436.     int i;
  437.     long flags;
  438.  
  439.     Memory = NULL;
  440.     add_cleanup(main_cleanup, "main");
  441.  
  442.     IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", INTUITION_REV);
  443.     if( IntuitionBase == NULL )
  444.     {
  445.         puts("can't open intuition\n");
  446.         cleanup(debug);
  447.         exit(20);
  448.     }
  449.  
  450.     GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",GRAPHICS_REV);
  451.     if( GfxBase == NULL )
  452.     {
  453.         puts("can't open graphics library\n");
  454.         cleanup(debug);
  455.         exit(20);
  456.     }
  457.  
  458.     LayersBase = OpenLibrary("layers.library", LAYERS_REV);
  459.     if (LayersBase == NULL)
  460.     {
  461.         puts("Can't open Layers Library\n");
  462.         cleanup(debug);
  463.         exit(20);
  464.     }
  465.  
  466.     RocketAudioInit();
  467.     show_init();
  468.  
  469.     if(( window = (struct Window *)OpenWindow(&NewWindow) ) == NULL)
  470.     {
  471.         puts("can't open window\n");
  472.         cleanup(debug);
  473.         exit(20);
  474.     }
  475.  
  476.     if(( badwindow = (struct Window *)OpenWindow(&BadWindow) ) == NULL)
  477.     {
  478.         puts("can't open obstacle\n");
  479.         cleanup(debug);
  480.         exit(20);
  481.     }
  482.  
  483.     viewport = ViewPortAddress(window);
  484.  
  485.     if((rocket_sprite = GetSprite(&rocket, 2)) == -1)
  486.         if((rocket_sprite = GetSprite(&rocket, 4)) == -1)
  487.         if((rocket_sprite = GetSprite(&rocket, 6)) == -1) {
  488.             puts("can't get rocket_sprite\n");
  489.             cleanup(debug);
  490.             exit(20);
  491.         }
  492.     if((saucer_sprite = GetSprite(&saucer, rocket_sprite+1)) == -1) {
  493.         puts("can't get saucer_sprite\n");
  494.         cleanup(debug);
  495.         exit(20);
  496.     }
  497.     rocket.x = 0;
  498.     rocket.y = 0;
  499.     rocket.height = ROCKETHEIGHT;
  500.     saucer.x = 0;
  501.     saucer.y = 0;
  502.     saucer.height = SAUCERHEIGHT;
  503.  
  504.     coloregs = ((rocket_sprite & 0x06)*2)+16;
  505.  
  506.     for(i = 0; i < 3; i++)
  507.         SetRGB4(viewport, coloregs+1+i,
  508.             sprite_colors[i]&0x000F,
  509.             (sprite_colors[i]&0x00F0)>>4,
  510.             (sprite_colors[i]&0x0F00)>>8);
  511.  
  512.     if(!(rbuf = AllocRemember(&Memory, 4L * ROCKETHEIGHT + 8L, MEMF_CHIP))) {
  513.         cleanup(debug);
  514.         exit(20);
  515.     }
  516.  
  517.     if(!(sbuf = AllocRemember(&Memory, 4L * SAUCERHEIGHT + 8L, MEMF_CHIP))) {
  518.         cleanup(debug);
  519.         exit(20);
  520.     }
  521.  
  522.     init_timer();
  523.     init_joy();
  524.  
  525.     buttons = 0;
  526.     recalc_rocket();
  527.     set_saucer(0);
  528.  
  529.     KeepGoing = TRUE;
  530.  
  531.     timeout = 0;
  532.     cycle_timeout = 10;
  533.     cycle_position = 0;
  534.     autoflag = 1;
  535.     automode = 'F';
  536.  
  537.     saucer_timeout = SAUCERDELAY;
  538.     saucer_up = 0;
  539.     MoveSprite(viewport, &saucer, -20, -20);
  540.  
  541.     SetWindowTitles(window, -1, title[0]);
  542.     titmode = 0;
  543.     x = y = 200;
  544.     vx = 100;
  545.     vy = 0;
  546.     ax = 0;
  547.     ay = 10;
  548.     MoveSprite(viewport, &rocket, x/SCALEFACTOR, y/SCALEFACTOR);
  549.  
  550.     while( KeepGoing )
  551.     {
  552.         flags = Wait((1 << window->UserPort->mp_SigBit) |
  553.                      (1 << badwindow->UserPort->mp_SigBit) |
  554.                      (1 << eagle1sound.port->mp_SigBit) |
  555.                      (1 << eagle2sound.port->mp_SigBit) |
  556.                      (1 << gameIOMsg->mn_ReplyPort->mp_SigBit) |
  557.                      (1 << tr->tr_node.io_Message.mn_ReplyPort->mp_SigBit));
  558.         WaitTOF();
  559.  
  560.         if(flags & (1 << eagle1sound.port->mp_SigBit)) {
  561.             while(DoneMessage=(struct IOAudio *)GetMsg(eagle1sound.port) )
  562.                 Eagle1Done();
  563.             ShowControl();
  564.             HideEagle();
  565.         }
  566.  
  567.         if(flags & (1 << eagle2sound.port->mp_SigBit)) {
  568.             while(DoneMessage=(struct IOAudio *)GetMsg(eagle2sound.port) )
  569.                 Eagle2Done();
  570.             if(autoflag && automode == 'P')
  571.                 reinit();
  572.             HideControl();
  573.         }
  574.  
  575.         if(flags & (1 << badwindow->UserPort->mp_SigBit))
  576.             while(NewMessage=(struct IntuiMessage *)GetMsg(badwindow->UserPort) )
  577.             {
  578.                 int class = NewMessage->Class;
  579.                 ReplyMsg( NewMessage );
  580.                 switch( class )
  581.                 {
  582.                 case CLOSEWINDOW:
  583.                     KeepGoing = FALSE;
  584.                     break;
  585.                 }
  586.             }
  587.  
  588.         if(flags & (1 << gameIOMsg->mn_ReplyPort->mp_SigBit)) {
  589.             if(GetMsg(gameIOMsg->mn_ReplyPort)) {
  590.                 JoyMove(gameEvent.ie_X, gameEvent.ie_Y);
  591.                 SendGameIO();
  592.             }
  593.         }
  594.  
  595.         if(flags & (1 << tr->tr_node.io_Message.mn_ReplyPort->mp_SigBit)) {
  596.             if(GetMsg(tr->tr_node.io_Message.mn_ReplyPort)) {
  597.  
  598.                 if(exploding) {
  599.                     explode();
  600.                 } else {
  601.                     if(timeout > 0) {
  602.                         timeout--;
  603.                         if(timeout == 0) {
  604.                             SetWindowTitles(badwindow, BadWindow.Title, -1);
  605.                             display_cycle();
  606.                             cycle_timeout = 10;
  607.                         }
  608.                     } else if(timeout == 0) {
  609.                         cycle_timeout--;
  610.                         if(cycle_timeout <= 0) {
  611.                             cycle_timeout = 10;
  612.                             cycle_position++;
  613.                             if(cycle[cycle_position]==0)
  614.                                 cycle_position = 0;
  615.                             display_cycle();
  616.                         }
  617.                     }
  618.                     if(saucer_timeout == 0) {
  619.                         int dx, dy;
  620.                         PlaySaucer();
  621.                         if(saucer_up == 0) {
  622.                             saucer_up = 1;
  623.                             saucer_x = 200;
  624.                             saucer_y = 200;
  625.                             saucer_cycle = 0;
  626.                         }
  627.                         set_saucer(saucer_cycle++);
  628.                         if(saucer_cycle >= 3)
  629.                             saucer_cycle = 0;
  630.                         dx = dy = 0;
  631.                         if(saucer_x < x-SAUCERSPEED)
  632.                             dx = SAUCERSPEED;
  633.                         else if(saucer_x > x+SAUCERSPEED)
  634.                             dx = -SAUCERSPEED;
  635.                         if(saucer_y < y-SAUCERSPEED)
  636.                             dy = SAUCERSPEED;
  637.                         else if(saucer_y > y+SAUCERSPEED)
  638.                             dy = -SAUCERSPEED;
  639.                         if(dy == 0) dx += dx/2;
  640.                         if(dx == 0) dy += dy/2;
  641.                         saucer_x += dx;
  642.                         saucer_y += dy;
  643.                         MoveSprite(viewport, &saucer,
  644.                             saucer_x/SCALEFACTOR, saucer_y/SCALEFACTOR);
  645.                     } else  {
  646.                         if(saucer_timeout != -1)
  647.                             saucer_timeout--;
  648.                         if(saucer_up) {
  649.                             saucer_up = 0;
  650.                             MoveSprite(viewport, &saucer, -20, -20);
  651.                         }
  652.                     }
  653.  
  654.                     if(autoflag)
  655.                         AutoPilot();
  656.                     x += vx;
  657.                     y += vy;
  658.                     vx += ax;
  659.                     vy += ay;
  660.  
  661.                     if(x > XMAX) x = XMIN;
  662.                     if(x < XMIN) x = XMAX;
  663.                     if(y < YMIN) y = YMAX;
  664.                     if(y > YMAX) y = YMIN;
  665.  
  666.                     switch(HitWindow()) {
  667.                         case OK:
  668.                             if(ay==0) {
  669.                                 ay = 10;
  670.                                 timeout = 10;
  671.                                 saucer_timeout = SAUCERDELAY;
  672.                             }
  673.                             break;
  674.                         case LANDED:
  675.                             if(vy >= -2*SCALEFACTOR && vy < 0) {
  676.                                 timeout = 10;
  677.                                 saucer_timeout = SAUCERDELAY;
  678.                                 break;
  679.                             }
  680.                                if(vy >= 0 && vy <= SCALEFACTOR &&
  681.                                vx >= -20 && vx <= 20
  682.                             ) {
  683.                                 if(timeout >= 0) {
  684.                                     if(vy <= 30 && vx == 0)
  685.                                         SetWindowTitles(window, "Great Landing!", -1);
  686.                                     else if(vy <= 70 && vx == 0)
  687.                                         SetWindowTitles(window, "Good Landing.", -1);
  688.                                     else
  689.                                         SetWindowTitles(window, "Just made it...", -1);
  690.                                     ShowEagle();
  691.                                     LandedAudio();
  692.                                 }
  693.                                 timeout = -1;
  694.                                 vx = vy = 0;
  695.                                 ax = ay = 0;
  696.                                 delflame(ALLFLAMES);
  697.                                 saucer_timeout = -1;
  698.                                 automode = 'P';
  699.                                 break;
  700.                             }
  701.                         case CRASHEDGOOD:
  702.                             SetWindowTitles(window, "OUCH! That hurt!", -1);
  703.                             explode();
  704.                             break;
  705.                         case CRASHEDBAD:
  706.                             SetWindowTitles(badwindow, "OUCH! That hurt!", -1);
  707.                             explode();
  708.                             break;
  709.                         case CRASHEDSAUCER:
  710.                             SetWindowTitles(window, "GOTCHA!", -1);
  711.                             explode();
  712.                             break;
  713.                     }
  714.                     MoveSprite(viewport, &rocket,
  715.                         x/SCALEFACTOR, y/SCALEFACTOR);
  716.                 }
  717.                 SendTimeIO();
  718.             }
  719.         }
  720.  
  721.         if(flags & (1 << window->UserPort->mp_SigBit))
  722.             while( NewMessage=(struct IntuiMessage *)GetMsg(window->UserPort) )
  723.             {
  724.                 int class = NewMessage->Class;
  725.                 int code = NewMessage->Code;
  726.                 ReplyMsg( NewMessage );
  727.                 switch( class )
  728.                 {
  729.                 case CLOSEWINDOW:
  730.                     KeepGoing = FALSE;
  731.                     break;
  732.                 case RAWKEY:
  733.                     if(autoflag) {
  734.                         autoflag = 0;
  735.                         delflame(ALLFLAMES);
  736.                     }
  737.                     switch(code) {
  738.                         case 0x4C:
  739.                             addflame(MAINFLAME);
  740.                             ay = -20; 
  741.                             break;
  742.                         case 0x4C|0x80:
  743.                             delflame(MAINFLAME);
  744.                             ay = 10; 
  745.                             break;
  746.                         case 0x4E:
  747.                             addflame(LEFTFLAME);
  748.                             ax = (buttons&RIGHTFLAME)?0:10;
  749.                             break;
  750.                         case 0x4E|0x80:
  751.                             delflame(LEFTFLAME);
  752.                             ax = (buttons&RIGHTFLAME)?-10:0;
  753.                             break;
  754.                         case 0x4F:
  755.                             addflame(RIGHTFLAME);
  756.                             ax = (buttons&LEFTFLAME)?0:-10;
  757.                             break;
  758.                         case 0x4F|0x80:
  759.                             delflame(RIGHTFLAME);
  760.                             ax = (buttons&LEFTFLAME)?10:0;
  761.                             break;
  762.                     }
  763.                     break;
  764.                 }   /* end of switch (class) */
  765.             }   /* end of while ( newmessage )*/
  766.     }  /* end while ( keepgoing ) */
  767.     cleanup(debug);
  768.     exit(0);
  769. } /* end of main */
  770.  
  771. AutoPilot()
  772. {
  773.     static int lastwx = -1, lastwy = -1;
  774.     if(lastwx != window->LeftEdge || lastwy != window->TopEdge) {
  775.         if(lastwx != -1) {
  776.             timeout = 10;
  777.             saucer_timeout = SAUCERDELAY;
  778.             automode = 'G';
  779.         }
  780.         lastwx = window->LeftEdge;
  781.         lastwy = window->TopEdge;
  782.     }
  783.     switch(automode) {
  784.         case 'F': Fall(); break;
  785.         case 'G': GetThere(); break;
  786.         case 'H': Hover(); break;
  787.         case 'L': LandIt(); break;
  788.         case 'P': break;
  789.         default: break;
  790.     }
  791. }
  792.  
  793. Fall()
  794. {
  795.     if(y > (window->TopEdge / 2) * SCALEFACTOR)
  796.         automode = 'G';
  797.     setvxy(vx, vy);
  798. }
  799.  
  800. GetThere()
  801. {
  802.     int wantvx, wantvy;
  803.  
  804.     int wanty = (window->TopEdge-ROCKETHEIGHT-2)*SCALEFACTOR;
  805.     int wantx = (window->LeftEdge+window->Width/2)*SCALEFACTOR;
  806.  
  807.     if(x < wantx-10) wantvx = SCALEFACTOR;
  808.     else if(x > wantx+10) wantvx = -SCALEFACTOR;
  809.     else wantvx = 0;
  810.     if(y > wanty-10) wantvy = -SCALEFACTOR;
  811.     else if(y < wanty+10) wantvy = SCALEFACTOR;
  812.     else wantvy = 0;
  813.  
  814.     if(x >= wantx-10*SCALEFACTOR && x <= wantx+10*SCALEFACTOR)
  815.         automode = 'H';
  816.  
  817.     setvxy(wantvx, wantvy);
  818. }
  819.  
  820. Hover()
  821. {
  822.     if(vx <= 10 && vx >= -10 && vy <= 10 && vy >= -10)
  823.         automode = 'L';
  824.     setvxy(0, 0);
  825. }
  826.  
  827. setvxy(wantvx, wantvy)
  828. int wantvx, wantvy;
  829. {
  830.     int wantax, wantay;
  831.  
  832.     if(vx < wantvx-10) wantax = 10;
  833.     else if(vx > wantvx+10) wantax = -10;
  834.     else wantax = 0;
  835.  
  836.     if(vy < wantvy-10) wantay = 10;
  837.     else if(vy > wantvy+10) wantay = -10;
  838.     else wantay = 0;
  839.  
  840.     if(wantax != ax) {
  841.         switch(wantax) {
  842.             case -10: delflame(LEFTFLAME); addflame(RIGHTFLAME); break;
  843.             case 0: delflame(LEFTFLAME | RIGHTFLAME); break;
  844.             case 10: delflame(RIGHTFLAME); addflame(LEFTFLAME); break;
  845.         }
  846.         ax = wantax;
  847.     }
  848.     if(wantay != ay) {
  849.         switch(wantay) {
  850.             case -10: addflame(MAINFLAME); ay = -20; break;
  851.             case 0: break;
  852.             case 10: delflame(MAINFLAME); ay = 10; break;
  853.         }
  854.     }
  855. }
  856.  
  857. LandIt()
  858. {
  859.     setvxy(0, 50);
  860. }
  861.  
  862. HitWindow()
  863. {
  864.     int sx = x/SCALEFACTOR;
  865.     int sy = y/SCALEFACTOR;
  866.     int ret;
  867.  
  868.     ret = checkwindow(sx, sy, window, 1);
  869.     if(!ret)
  870.         ret = checkwindow(sx, sy, badwindow, 0);
  871.     if(!ret)
  872.         ret = checksaucer();
  873.     if(ret)
  874.         automode = 'P';
  875.     return ret;
  876. }
  877.  
  878. checkwindow(sx, sy, window, canland)
  879. int sx, sy;
  880. struct Window *window;
  881. int canland;
  882. {
  883.     int top = window->TopEdge-ROCKETHEIGHT+3;
  884.     int bottom = window->TopEdge+window->Height - 2;
  885.     int left = window->LeftEdge-SPRWIDTH+4*PIXRATIO;
  886.     int right = window->LeftEdge+window->Width-5*PIXRATIO;
  887.  
  888.     if(sx<left || sx>right) return OK;
  889.     if(sy>bottom || sy<top) return OK;
  890.     if(canland) {
  891.         if(sy>top+3) return CRASHEDGOOD;
  892.         if(sx<left+7*PIXRATIO || sx>right-7*PIXRATIO) return CRASHEDGOOD;
  893.         return LANDED;
  894.     } else {
  895.         return CRASHEDBAD;
  896.     }
  897. }
  898.  
  899. checksaucer()
  900. {
  901.     int sx, sy, rx, ry, top, bottom, left, right;
  902.  
  903.     if(!saucer_up) return OK;
  904.  
  905.     rx = x/SCALEFACTOR;
  906.     ry = y/SCALEFACTOR;
  907.     sx = saucer_x/SCALEFACTOR;
  908.     sy = saucer_y/SCALEFACTOR;
  909.  
  910.     top = sy-ROCKETHEIGHT+3;
  911.     bottom = sy+SAUCERHEIGHT - 2;
  912.     left = sx-SPRWIDTH+4*PIXRATIO;
  913.     right = sx+SPRWIDTH-5*PIXRATIO;
  914.  
  915.     if(rx<left || rx>right) return OK;
  916.     if(ry>bottom || ry<top) return OK;
  917.     return CRASHEDSAUCER;
  918. }
  919.  
  920. trash_timer()
  921. {
  922.     AbortIO(tr);
  923.     DeleteTimer(tr);
  924. }
  925.  
  926. init_timer()
  927. {
  928.     if(!(tr = CreateTimer(UNIT_VBLANK))) {
  929.         printf("Can't create timer.\n");
  930.         cleanup(debug);
  931.         exit(20);
  932.     }
  933.     SendTimeIO();
  934.     add_cleanup(trash_timer, "timer");
  935. }
  936.  
  937. SendTimeIO()
  938. {
  939.     tr->io_Command = TR_ADDREQUEST;
  940.     tr->tr_time.tv_secs = 0;
  941.     tr->tr_time.tv_micro = 100000L;
  942.  
  943.     SendIO(tr);
  944. }
  945.  
  946. trash_joy()
  947. {
  948.     if(gameIOPending) AbortIO(gameIOMsg);
  949.     if(ControllerType != GPCT_NOCONTROLLER)
  950.         SetControllerType(GPCT_NOCONTROLLER);
  951.     if(GameportOpen) CloseDevice(gameIOMsg);
  952.     if(gameIOMsg) DeleteStdIO(gameIOMsg);
  953.     if(gameMsgPort) DeletePort(gameMsgPort);
  954. }
  955.  
  956. extern struct MsgPort *CreatePort();
  957. extern struct IOStdReq *CreateStdIO();
  958.  
  959. init_joy()
  960. {
  961.     gameIOMsg = 0;
  962.     gameMsgPort = 0;
  963.     ControllerType = GPCT_NOCONTROLLER;
  964.     GameportOpen = 0;
  965.     gameIOPending = 0;
  966.     add_cleanup(trash_joy, "joystick");
  967.     if(!(gameMsgPort = CreatePort(0, 0))) {
  968.         printf("Can't create joystick port\n");
  969.         cleanup(debug);
  970.         exit(20);
  971.     }
  972.     if(!(gameIOMsg = CreateStdIO(gameMsgPort))) {
  973.         printf("Can't create joystick message.\n");
  974.         cleanup(debug);
  975.         exit(20);
  976.     }
  977.     if(OpenDevice("gameport.device", 1, gameIOMsg, 0) != 0) {
  978.         printf("Can't open gameport.device.\n");
  979.         cleanup(debug);
  980.         exit(20);
  981.     }
  982.     GameportOpen = 1;
  983.     if(SetControllerType(GPCT_ABSJOYSTICK) != 0) {
  984.         printf("Can't set controller type.\n");
  985.         cleanup(debug);
  986.         exit(20);
  987.     }
  988.     ControllerType = GPCT_ABSJOYSTICK;
  989.     if(SetControllerTrigger() != 0) {
  990.         printf("Can't set controller trigger.\n");
  991.         cleanup(debug);
  992.         exit(20);
  993.     }
  994.     SendGameIO();
  995. }
  996.  
  997. SendGameIO()
  998. {
  999.     gameIOMsg->io_Command = GPD_READEVENT;
  1000.     gameIOMsg->io_Data = (APTR)&gameEvent;
  1001.     gameIOMsg->io_Length = sizeof(gameEvent);
  1002.     gameIOMsg->io_Flags = 0;
  1003.  
  1004.     SendIO(gameIOMsg);
  1005.     gameIOPending = 1;
  1006. }
  1007.  
  1008. SetControllerType(type)
  1009. SHORT type;
  1010. {
  1011.     BYTE buffer[1];
  1012.     gameIOMsg->io_Command = GPD_SETCTYPE;
  1013.     gameIOMsg->io_Length = 1;
  1014.     gameIOMsg->io_Data = (APTR)buffer;
  1015.     buffer[0] = type;
  1016.     SendIO(gameIOMsg);
  1017.     WaitPort(gameMsgPort);
  1018.     GetMsg(gameMsgPort);
  1019.     return (int)gameIOMsg->io_Error;
  1020. }
  1021.  
  1022. SetControllerTrigger()
  1023. {
  1024.     struct GamePortTrigger gpt;
  1025.     gameIOMsg->io_Command = GPD_SETTRIGGER;
  1026.     gameIOMsg->io_Length = sizeof(gpt);
  1027.     gameIOMsg->io_Data = (APTR)&gpt;
  1028.     gpt.gpt_Keys = GPTF_UPKEYS|GPTF_DOWNKEYS;
  1029.     gpt.gpt_Timeout = 0;
  1030.     gpt.gpt_XDelta = 1;
  1031.     gpt.gpt_YDelta = 1;
  1032.  
  1033.     return DoIO(gameIOMsg);
  1034. }
  1035.